.pragma library
.import DataMan 0.1 as DM
.import "utils.js" as Utils

/*************| 全局数据定义 |***************/
var COL, ROW, ELEN, MONSTN;
var MonsterComp = Qt.createComponent("qml/Monster.qml");
var GameScComp = Qt.createComponent("qml/GameScore.qml");
var MonSt = {Normal: 0, Marked: 1, Dead: 2};
var GameSt = {Start: 0, Playing: 1, Droping: 2, End: 3};
var state = GameSt.End;
var garr = [];
var marr = [];
var propN = [];
var markedArr = [];
var nowProp = DM.DataMan.PNONE;
var game = {};
var targetScore = 0;

/*************| 函数定义 |***************/
// 首先调用这个初始化
function init(d)
{
    COL = d.col;
    ROW = d.row;
    MONSTN = d.monstn;
    ELEN = COL * ROW;
    state = GameSt.End;
}


// 同步本地数据
function syncData(fromNative)
{
	var i, j;
	var k = 0;
	if (fromNative) {
		var arr = DM.DataMan.garr;
		for (i = 0; i < COL; ++i) {
			if (!garr[i]) {
				garr[i] = new Array(ROW);
				marr[i] = new Array(ROW);
			}
			for (j = 0; j < ROW; ++j) {
				garr[i][j] = arr[k + j];
			}
			k += COL;
		}
		propN = DM.DataMan.propN;
	} else {
		arr = new Array(ELEN);
		for ( i = 0; i < COL; ++i) {
			for ( j = 0; j < ROW; ++j)
				arr[k + j] = garr[i][j];
			k += COL;
		}
		DM.DataMan.garr = arr;
		DM.DataMan.propN = propN;
	}
}

function swapEle(c1, r1, c2, r2)
{
	var k = garr[c1][r1];
	garr[c1][r1] = garr[c2][r2];
	garr[c2][r2] = k;
	k = marr[c1][r1];
	marr[c1][r1] = marr[c2][r2];
	marr[c2][r2] = k;
	return k;
}

function doDrop()
{
	state = GameSt.Droping;
	game.moven = 0;
	var ele;
	var r2l = function() {
		var m = 0;
		for (var col = 0; col < COL; ++col) {
			if (DM.DataMan.MNONE === garr[col][ROW - 1]) {
				++m;
			} else if (m > 0) {
				++game.moven;
				for (var row = ROW - 1; row >= 0; --row) {
					if (DM.DataMan.MNONE === garr[col][row])
						break;
					ele = swapEle(col, row, col - m, row);
					if (row === ROW - 1) {
						markedArr.push([ele, m, true]);
					} else {
						markedArr.push([ele, m, false]);
					}
				}
			}
		}
		if (0 === game.moven) {
			victoryCheck();
		} else {
			markedArr.reverse();
			game.timer.interval = 80;
			game.timer.timeoutfunc = function() {
				var i = Math.floor(Math.random() * 5) + 1;
				while (i-->0) {
					ele = markedArr.pop();
					if (!ele) {
						game.timer.stop();
						return;
					}
					if (ele[2])	{
						ele[0].walkByX(-game.eleW, ele[1], function() {
							--game.moven;
							if (0 === game.moven)
								victoryCheck();
						});
					} else {
						ele[0].walkByX(-game.eleW, ele[1], null);
					}
				}
			};
			game.timer.start();
		}
	};

	var hasEmtCol = false;
	for (var col = 0; col < COL; ++col) {
		var m = 0;
		for (var row = ROW - 1; row >= 0; --row) {
			if (DM.DataMan.MNONE === garr[col][row]) {
				++m;
			} else if (m > 0){
				++game.moven;
				ele = swapEle(col, row, col, row + m);
				ele.dropY(m * game.eleH, function(){
					--game.moven;
					if (0 === game.moven) {
						r2l();
					}
				});
			}
		}
		if (ROW === m)
			hasEmtCol = true;
	}
	if (0 === game.moven) {
		if (hasEmtCol)
			r2l();
		else
			victoryCheck();
	}
}

function idxOk(col, row)
{
	return (col >= 0) && (col < COL) && (row >= 0) && (row < ROW);
}

function moveCheck()
{
	for (var col = 0, tc = 1; col < COL; ++col, ++tc) {
		if (DM.DataMan.MNONE === garr[col][ROW - 1])
			return false;
		for (var row = ROW - 1, tr = ROW - 2; row >= 0; --row, --tr) {
			if (DM.DataMan.MNONE === garr[col][row])
				break;
			if (idxOk(col, tr) && (DM.DataMan.MNONE !== garr[col][tr]) && (garr[col][row] === garr[col][tr]))
				return true;
			if (idxOk(tc, row) && (garr[tc][row] !== DM.DataMan.MNONE) && (garr[col][row] === garr[tc][row]))
				return true;
		}
	}
	return false;
}

function victoryCheck()
{
	game.canmove = moveCheck();
	game.win = DM.DataMan.nowSc >= targetScore;
	if (!game.canmove) {
		state = GameSt.End;
		if (garr[0][ROW - 1] === DM.DataMan.MNONE) {
			// 清屏奖励
			addScore(200, Utils.AppWin.width / 2 - 50, 300, 0.7);
			game.win = DM.DataMan.nowSc >= targetScore;
		}
		if (game.win) {
			enterNextLv();
		} else {
			if (game.canUseProp)
				game.tipUsePropDialog.visible = true;
		}
	} else {
		state = GameSt.Playing;
	}
}

function enterNextLv()
{
	if (!game.win) return;
	state = GameSt.End;
	if (garr[0][ROW - 1] !== DM.DataMan.MNONE) {
		clearScr();
	}
	DM.DataMan.lv = DM.DataMan.lv + 1;
	startGame(true);
}

function clearScr()
{
	// 每个小怪兽给5分
	var add = 0;
	var mr = ROW - 1;
	for (var col = 0; col < COL; ++col) {
		if (DM.DataMan.MNONE === garr[col][ROW - 1])
			break;
		for (var row = ROW - 1; row >= 0; --row) {
			if (DM.DataMan.MNONE === garr[col][row])
				break;
			add += 5;
			marr[col][row].st = MonSt.Dead;
			if (row < mr)
				mr = row;
		}
	}
	if (add > 0) {
		addScore(add, col / 2 * game.eleW, (ROW - mr) / 2 * game.eleH, 0.5);
	}
}

function markedEle2St(st)
{
	for (var i = 0; i < markedArr.length; ++i) {
		var e = markedArr[i];
		marr[e[0]][e[1]].st = st;
	}
}

function getScore4n(n)
{
	return 5 * n  * n;
}

function doSearch(col, row, serT, mArr)
{
	if (!idxOk(col, row))
		return;
	var nidx = col + row * COL;
	if (DM.DataMan.MNONE === garr[col][row] || serT !== garr[col][row] || mArr[nidx])
		return;
	mArr[nidx] = true;
	markedArr[markedArr.length] = [col, row];
	doSearch(col, row - 1, serT, mArr);
	doSearch(col, row + 1, serT, mArr);
	doSearch(col - 1, row, serT, mArr);
	doSearch(col + 1, row, serT, mArr);
}

// 开始游戏游戏
function startGame(isnew)
{
	game.viewMask.enabled = true;
	state = GameSt.Start;
	if (isnew) {
		var k = new Array(ELEN);
		var per = Math.floor(k.length / MONSTN);
		var ot = k.length % MONSTN;
		var i = 0;
		for (var t = 1; t <= MONSTN; ++t) {
			for (var j = 0; j < per; ++j){
				k[i] = t;
				++i;
			}
		}
		while (ot > 0) {
			k[i] = Math.floor(Math.random() * MONSTN) + 1;
			++i;
			--ot;
		}
		// 执行乱序操作
		for (i = k.length - 1; i >= 1 ; --i) {
			j = k[i];
			t = Math.floor(Math.random() * i);
			k[i] = k[t];
			k[t] = j;
		}
		t = 0;
		for (i = 0; i < COL; ++i) {
			for (j = 0; j < ROW; ++j) {
				garr[i][j] = k[t];
				++t;
			}
		}
	}
	game.nowProp = null;
	game.moven =0;
	markedArr = [];
	for (i = 0; i < COL; ++i) {
		// 创建小怪兽
		for (j = 0; j < ROW; ++j) {
			if (garr[i][j] !== DM.DataMan.MNONE) {
				var m = MonsterComp.createObject(game.view, {"tp": garr[i][j]});
				marr[i][j] = m;
				++game.moven;
				markedArr.push(posMonster(m, i, j));
			} else {
				marr[i][j] = null;
			}
		}
	}
	if (0 === game.moven) {
		beginGame();
	} else {
		game.timer.interval = 80;
		game.tmpN = 0;
		game.timer.timeoutfunc = function() {
			i = Math.floor(Math.random() * 5) + 1;
			while (i-->0) {
				k = markedArr.pop();
				if (!k) {
					game.timer.stop();
					return;
				}
				k[0].walkByX(k[1], k[2], function(){
					--game.moven;
					if (game.moven < 1)
						beginGame();
				});
			}
			if (DM.DataMan.music) {
				if (0 === (game.tmpN % 12)) {
					Utils.playEffect("monster_coming");
				}
			}
			++game.tmpN;
		}
		game.timer.start();
	}
}

function posMonster(m, col, row)
{
	m.y = game.eleH * row;
	var offsetN = (Math.random() < 0.5) ? (-1-Math.floor(Math.random() * COL / 2)) : (Math.floor(Math.random() * COL / 2) + COL);
	m.x = offsetN * game.eleW - 5;
	if (offsetN < 0)
		return [m, game.eleW, col - offsetN];
	else
		return [m, -game.eleW, offsetN - col];
}

function beginGame()
{
	markedArr = [];
	targetScore = targetSc();
	game.startCB();
	state = GameSt.Playing;
	victoryCheck();
	game.viewMask.enabled = false;
}

// 创建新游戏
function createGame(isnew, objarr, startCB)
{
	if (isnew) {
		DM.DataMan.reset();
		propN = DM.DataMan.propN;
	}
	game.canUseProp = 0;
	for (var i = 0; i < propN.length; ++i)
		game.canUseProp += propN[i];
	game.viewMask = objarr.viewMask;
	game.canUseProp -= propN[DM.DataMan.PZom];
	game.view = objarr.view;
	game.tipUsePropDialog = objarr.tipUsePropDialog;
	game.eleW = game.view.width / COL;
	game.eleH = game.view.height / ROW;
	game.scTip = objarr.scTip;
	game.timer = objarr.timer;
	game.startCB = startCB;
	startGame(isnew);
}

function endGame()
{
	game.moncache = [];
}

function addScore(sc, x, y, scale)
{
	var tmp = sc;
	sc += DM.DataMan.nowSc;
	DM.DataMan.nowSc = sc;
	if (DM.DataMan.highSc < sc) {
		DM.DataMan.highSc = sc;
	}
	// 生成加分文字
	GameScComp.createObject(game.view, {"x":x, "y":y, "scale":scale, "num": tmp, "z": 1});
}

function updateScoreTip(nm)
{
	if (nm < 1) {
		game.scTip.text = "";
		return;
	}

	var n = getScore4n(nm);
	var n1 = getScore4n(nm + 1);
	if (DM.DataMan.PDSc === nowProp) {
		n += n;
		n1 += n1;
	}
	game.scTip.text = nm + "个小怪" + n + "分," + (nm + 1) + "个" + n1 + "分";
}

// 处理点击
function handleTouch(col, row)
{
	if (GameSt.Playing !== state) return;
	var nm = markedArr.length;
	if (0 === nm) {
		var mArr = new Array(ELEN);
		for (var i = 0; i< ELEN; ++i) {
			mArr[i] = false;
		}
		doSearch(col, row, garr[col][row], mArr);
		if (markedArr.length < 2) {
			markedArr = [];
			return;
		}
		updateScoreTip(markedArr.length);
		markedEle2St(MonSt.Marked);
		return;
	}
	game.scTip.text = "";
	// 如果里面有东西
	var tmp = markedArr[0];
	if (garr[col][row] !== garr[tmp[0]][tmp[1]]) {
		markedEle2St(MonSt.Normal);
		markedArr = [];
		return;
	}
	// 加分，转到死亡状态
	if (DM.DataMan.music) {
		var effn = ["green", "red", "blue", "purple", "yellow"];
		Utils.playEffect(effn[garr[col][row] - 1]);
	}
	for (i = 0; i < nm; ++i) {
		tmp = markedArr[i];
		marr[tmp[0]][tmp[1]].st = MonSt.Dead;
		marr[tmp[0]][tmp[1]] = null;
		garr[tmp[0]][tmp[1]] = DM.DataMan.MNONE;
	}
	var sc = getScore4n(nm);
	if (DM.DataMan.PDSc === nowProp)
		sc += sc;
	tmp = markedArr[Math.floor(nm / 2)];
	addScore(sc, tmp[0] * game.eleW, tmp[1] * game.eleH, 0.5 + (nm / 3) * 0.1);
	markedArr = [];
	doDrop();
}

function targetSc()
{
	var r = 600
	if (DM.DataMan.lv > 1) {
		var pn = Math.floor(DM.DataMan.lv / 2);
		var en = (0 == DM.DataMan.lv % 2) ? pn - 1 : pn;
		r += pn * 800 + en * 1000;
	}
	return r
}

function propFunc(pobj)
{
	if (GameSt.Playing !== state) return;
	if (DM.DataMan.propN[pobj.type] === 0)
		return;
//	switch
	if (game.nowProp === pobj) {
	}
}
